package se.webbzon.boltzmann.effect;

import java.awt.Dimension;
import java.awt.geom.AffineTransform;

import se.webbzon.boltzmann.resource.Resources;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldcamera.WorldCameraPane;

public class ScreenTransitionEffect extends ScreenEffect {
	
	// The available properties for this effect
	public static final int REVERSED 			= (1<<0);
	public static final int VERTICAL			= (1<<1);
	public static final int HORIZONTAL 			= (1<<2);
	public static final int TOP					= (1<<3);
	public static final int BOTTOM				= (1<<4);
	public static final int LEFT				= (1<<5);
	public static final int RIGHT				= (1<<6);
	public static final int	FADE				= (1<<7);
	public static final int CLOCKWISE			= (1<<8);
	public static final int COUNTER_CLOCKWISE 	= (1<<9);
	
	// The properties for this transition effect
	private final int properties;
	
	// The (half) scaling of the transition
	private final double halfScaling;
	
	// The (2 * pi *) number of turns of the transition
	private final double twoPiNrOfTurns;
	
	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new screen transition effect with a given texture set name
	 * and a given duration. If the duration is negative then the effect will 
	 * last until termination. The transition effect will be created with the
	 * properties VERTICAL and HORIZONTAL. **/
	public ScreenTransitionEffect(String textureSetName, int duration) {
		this(VERTICAL + HORIZONTAL,textureSetName,duration);
	}

	/** Creates a new screen transition effect with a given set of properties,
	 * a given texture set name and a given duration. If the duration is 
	 * negative then the effect will last until termination. **/
	public ScreenTransitionEffect(	int transitionProperties, 
									String textureSetName, 
									int duration) {
		this(transitionProperties,1,1,textureSetName,duration);
	}
	
	/** Creates a new screen transition effect with a given set of properties,
	 * a given scaling factor, a given number of turns, a given texture set name 
	 * and a given duration. If the duration is negative then the effect 
	 * will last until termination. **/
	public ScreenTransitionEffect(	int transitionProperties,
									double scaling, double nrOfTurns,
									String textureSetName, 
									int duration) {
		super(Resources.getTextureSet(textureSetName), duration);
		this.properties = transitionProperties;
		this.halfScaling = scaling * 0.5;
		this.twoPiNrOfTurns = nrOfTurns * 2 * Math.PI;
	}
	
	/*============================================================
	Public Method
	============================================================*/

	@Override public void onEffectBegin(WorldArea world) {};

	@Override public void onEffectStep(WorldArea world) {};

	@Override public void onEffectEnd(WorldArea world) {};

	@Override public void onEffectDraw(WorldArea world, WorldCameraPane hud) {
		final Dimension d = new Dimension();
		hud.getLayer().getDimension(d);
		
		// Calculate the scaling of the transition 
		final double scale;
		if (isSet(properties,REVERSED))
			scale = getDuration() / (double) getStartupDuration();
		else
			scale = (1 - getDuration() / (double) getStartupDuration());
		
		// Get the maximal size of the transition
		final double maxSize = halfScaling * Math.max(d.getWidth(), d.getHeight());
		
		// Calculate the size
		final int width;
		if (isSet(properties,HORIZONTAL))
			width = (int) (maxSize * scale);
		else
			width = (int) maxSize;
		
		final int height;
		if (isSet(properties,VERTICAL))
			height = (int) (maxSize * scale);
		else
			height = (int) maxSize;
		
		// Calculate the position
		final int x;
		if (isSet(properties,LEFT))
			x = width;
		else if (isSet(properties,RIGHT))
			x = (int) d.getWidth() - width;
		else
			x = ((int) d.getWidth()) / 2;
		
		final int y;
		if (isSet(properties,TOP))
			y = height;
		else if (isSet(properties,BOTTOM))
			y = (int) d.getHeight() - height;
		else
			y = ((int) d.getHeight()) / 2;
		
		final double theta;
		if (isSet(properties,CLOCKWISE))
			theta = -twoPiNrOfTurns * scale;
		else if (isSet(properties,COUNTER_CLOCKWISE))
			theta = twoPiNrOfTurns * scale;
		else
			theta = 0;
		
		if (isSet(properties,FADE))
			hud.setTransparency((float) scale);
		
		// Create and set the transform
		AffineTransform transform = new AffineTransform();
		if (x != 0 || y != 0)
			transform.translate(x, y);
		if (width != 1 || height != 1)
			transform.scale(width, height);
		if (theta != 0)
			transform.rotate(theta);
		hud.setTransform(transform);
		
		// Draw the transition
		hud.drawTexture(getTexture(), -1, -1, 2, 2);
		
		// Reset the hud
		hud.resetTransform();
		hud.setTransparency(0);
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Returns true if the given property is set in the given properties. **/
	private static final boolean isSet(int properties, int property) {
		return ((properties & property) == property);
	}

}
